#pragma once
#include <iostream>
#include <cstdio>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define PATH "."
#define NAME "file"
#define K 0x66
#define CREATE "create"
#define USE "use"
#define SIZE 4069
#define ERROR(s)     \
    {                \
        perror("s"); \
        exit(1);     \
    }
using namespace std;
class Shm
{
private:
    void Create(int flg)
    {
        _shmid = shmget(_key, _capacity, flg);
        if (_shmid < 0)
            ERROR("shmget");
    }
    void Attach()
    {
        _ptr = shmat(_shmid, nullptr, 0);
        if ((long long)_ptr < 0)
            ERROR("shmat");
    }
    void Close()
    {
        int n = shmdt(_ptr);
        if (n < 0)
            ERROR("shmdt");
    }
    void Delete()
    {

        int n = shmctl(_shmid, IPC_RMID, nullptr);
        if (n < 0)
            ERROR("shmctl");
    }

public:
    Shm(string use_type, string path = PATH, size_t cpct = SIZE)
        : _ptr(nullptr), _use_type(use_type), _capacity(cpct)
    {
        _key = ftok(path.c_str(), K);
        if (_key < 0)
        {
            ERROR("ftok");
        }
        if (_use_type == CREATE)
            Create(IPC_CREAT | IPC_EXCL | 0666);
        else
            Create(IPC_CREAT);
        Attach();
    }
    void *getptr()
    {
        return _ptr;
    }
    size_t getsize()
    {
        return _capacity;
    }
    ~Shm()
    {
        Close();
        if (_use_type == CREATE)
            Delete();
    }

private:
    int _key;
    int _shmid;
    string _use_type;
    size_t _capacity;
    void *_ptr;
};